package com.peng.rpc.util;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.peng.rpc.enumeration.RpcError;
import com.peng.rpc.exception.RpcException;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 提供nacos服务注册发现的工具类
 * @author Wonderson
 * @email wpp.ds@foxmail.com
 * @date 2022/3/5 22:45
 */
@Slf4j
public class NacosUtil {

    private static final String SERVICE_ADDR = "192.168.56.1:8848";
    private static final NamingService namingService;
    private static InetSocketAddress address;
    private static final Set<String> serviceNames = new HashSet<>();

    static {
        try {
            namingService = NamingFactory.createNamingService(SERVICE_ADDR);
        } catch (NacosException e) {
            log.error("nacos连接建立失败：{}", e.getMessage());
            throw new RpcException(RpcError.SERVICE_REGISTRY_UNCONNECTED);
        }
    }

    public static NamingService getNamingService() {
        return namingService;
    }

    public static void register(String serviceName, InetSocketAddress inetSocketAddress) {
        try {
            synchronized (serviceName) {
                serviceNames.add(serviceName);
                address = inetSocketAddress;
                namingService.registerInstance(serviceName, inetSocketAddress.getHostName(), inetSocketAddress.getPort());
            }
        } catch (NacosException e) {
            log.error("注册服务：{}失败:{}", serviceName, e.getMessage());
            throw new RpcException(RpcError.SERVICE_REGISTER_FAILED);
        }
    }

    public static List<Instance> getAllInstances(String serviceName) throws NacosException {
        return namingService.getAllInstances(serviceName);
    }

    /**
     * 一个服务节点只可能记录自己的Host+Port，因此只要从Nacos注销自己的address下的service就可以了
     */
    public static void deregister() {
        synchronized (serviceNames) {
            String host = address.getHostName();
            int port = address.getPort();
            for (String serviceName : serviceNames) {
                try {
                    //这个方法应该可以保证若是serviceName没有这个address也不会出错
                    namingService.deregisterInstance(serviceName, host, port);
                } catch (NacosException e) {
                    log.error("注销{}:{}下的服务{}出错", host, port, serviceName);
                }
            }
        }
    }

}
